﻿using System;
using System.Collections.Generic;
using System.Windows.Controls;
using DataStore;
using DataStore.Domain;
using DataStore.Repositories;
using System.ComponentModel;
using System.Windows;
using Infrastructure.CurrentData;
using Infrastructure.ViewModels;
using NHibernate;
using UI.Controls;
using UI.Dialogs.Dictionaries;

namespace UI
{
	/// <summary>
	/// Interaction logic for Book.xaml
	/// </summary>
	public partial class BookControl : UserControl
	{
	    BookViewModel _book;

	    public BookControl()
	    {
	        InitializeComponent();

            if (!DesignerProperties.GetIsInDesignMode(this))
            {
                _book = new BookViewModel(new DataStore.Domain.Book());
                this.DataContext = _book;
                // TODO Change OtherClassification to create-on-write
                _book.OtherClassification = new Classification();
            }

            SetPublishingFormatList();
            LoadSelectedCategories();
            LoadSelectedKeywords();

            CategoryList.SelectionChanged += CategoryList_SelectionChanged;
            KeywordList.SelectionChanged += KeywordList_SelectionChanged;

            // TODO Init viewmodels with lazy loading
            AllAuthorsViewModel authorVMs = new AllAuthorsViewModel();
            authorsList.DataContext = authorVMs.Authors;
            addAuthor.Saved += delegate
                                   {
                                       authorVMs.RefreshAuthors();
                                   };

            AllCountriesViewModel countriesVM = new AllCountriesViewModel();
	        Country.ItemsSource = countriesVM.Countries;

            AllLanguagesViewModel languagesVM = new AllLanguagesViewModel();
	        Language.ItemsSource = languagesVM.Languages;

            AllCompaniesViewModel companiesVM = new AllCompaniesViewModel();
	        Publishers.ItemsSource = companiesVM.Companies;
	        Publishers.DisplayMemberPath = "Name";

            GetAuthors();
            LoadCovers();
	        LoadLinks();

            _book.PropertyChanged += delegate(object sender, PropertyChangedEventArgs e)
                                         {
                                             if(e.PropertyName == "Cover")
                                             {
                                                 LoadCovers();
                                             }
                                         };
	    }

	    void LoadLinks()
	    {
	        Links.ItemsSource = _book.Links;
	    }

	    /// <summary>
        /// Loads the covers.
        /// </summary>
	    void LoadCovers()
	    {
            FrontCovers.ItemsSource = _book.FrontCovers;
            BackCovers.ItemsSource = _book.BackCovers;
	    }


	    void KeywordList_SelectionChanged(object sender, EventArgs e)
        {
            _book.Keywords = KeywordList.SelectedKeywords;
        }

        /// <summary>
        /// Loads the comment into the comment control.
        /// </summary>
	    void LoadComment()
	    {
            if (!string.IsNullOrEmpty(_book.Comment))
            {
                Comment.Document = _book.Comment;
            }
	    }

	    void CategoryList_SelectionChanged(object sender, Microsoft.Windows.Controls.DataGridRowEditEndingEventArgs e)
        {
            _book.Categories = CategoryList.SelectedCategories;
        }

        /// <summary>
        /// Loads the selected categories.
        /// </summary>
	    void LoadSelectedCategories()
	    {
	        if(_book != null)
	        {
                if (!NHibernateUtil.IsInitialized(_book.Categories))
                {
                    IDatabase database = Current.Container.Resolve<IDatabase>();
                    using (var unitOfWork = database.CreateUnitOfWork())
                    {
                        ISession session = unitOfWork.Session;
                        session.Lock(_book.Book, LockMode.Read);
                        NHibernateUtil.Initialize(_book.Categories);
                    }
                }

	            CategoryList.SelectedCategories = _book.Categories;
	        }
	    }

        /// <summary>
        /// Loads the selected keywords.
        /// </summary>
        void LoadSelectedKeywords()
        {
            if (_book != null)
            {
                if(!NHibernateUtil.IsInitialized(_book.Keywords))
                {
                    IDatabase database = Current.Container.Resolve<IDatabase>();
                    using (var unitOfWork = database.CreateUnitOfWork())
                    {
                        ISession session = unitOfWork.Session;
                        session.Lock(_book.Book, LockMode.Read);
                        NHibernateUtil.Initialize(_book.Keywords);
                    }

                }

                KeywordList.SelectedKeywords = _book.Keywords;
            }
        }

        /// <summary>
        /// Loads the publishing format list.
        /// </summary>
	    void SetPublishingFormatList()
	    {
            if (!DesignerProperties.GetIsInDesignMode(this))
            {
                List<PublishingFormat> publishingFormats = null;

                IDatabase database = Current.Container.Resolve<IDatabase>();
                using (var unitOfWork = database.CreateUnitOfWork())
                {
                    IRepository<PublishingFormat> pf = new PublishingFormatRepository(unitOfWork);
                    publishingFormats = pf.All as List<PublishingFormat>;
                }
                format.ItemsSource = publishingFormats;
                if (publishingFormats != null) format.SelectedItem = publishingFormats[0];
            }
	    }

        /// <summary>
        /// Returns the new book.
        /// </summary>
        /// <value>The book.</value>
	    public Book Book
	    {
	        get
	        {
	            _book.Categories = CategoryList.SelectedCategories;
	            _book.Keywords = KeywordList.SelectedKeywords;
               
                if(string.IsNullOrEmpty(Comment.Document))
                {
                    _book.Comment = null;
                }
                else
                {
                    _book.Comment = Comment.Document;
                }


	            return _book.Book;
	        }
	    }

        /// <summary>
        /// Gets or sets the book viewmodel.
        /// </summary>
        /// <value>The book viewmodel.</value>
	    public BookViewModel BookVM
	    {
            get
            {
                return _book;
            }
	        set
	        {
	            _book = value;

                InitLazyFields();

	            DataContext = _book;
	            authors.ItemsSource = _book.Authors;
	            LoadComment();
                LoadSelectedCategories();
                LoadSelectedKeywords();
                // TODO Change OtherClassification to create-on-write
                if (_book.OtherClassification == null) _book.OtherClassification = new Classification();
                LoadCovers();
                LoadLinks();

	            
	        }
	    }

        /// <summary>
        /// Initialize lazy fields before binding
        /// </summary>
	    void InitLazyFields()
	    {
	        IDatabase database = Current.Container.Resolve<IDatabase>();
	        using(var unitOfWork = database.CreateUnitOfWork())
	        {
	            ISession session = unitOfWork.Session;
                session.Lock(_book.Book, LockMode.Read);

	            if (!NHibernateUtil.IsInitialized(_book.Format))
	            {
                    NHibernateUtil.Initialize(_book.Format);
	            }

                if (!NHibernateUtil.IsInitialized(_book.Authors))
                {
                    NHibernateUtil.Initialize(_book.Authors);
                }
	        }
	    }

	    private void Comment_DocumentChanged(object sender, EventArgs e)
        {
            _book.Comment = Comment.Document;
        }

        private void addAuthor_CancelClicked(object sender, EventArgs e)
        {
            addAuthorExpander.IsExpanded = false;
        }

        private void addAuthorExpander_Expanded(object sender, RoutedEventArgs e)
        {
            SwitchAuthorExpander(sender);
        }

        private void selectAuthorExpander_Expanded(object sender, RoutedEventArgs e)
        {
            SwitchAuthorExpander(sender);
        }

        /// <summary>
        /// Switches between author expanders.
        /// Only one expander can be opened.
        /// </summary>
        /// <param name="sender">The sender.</param>
	    void SwitchAuthorExpander(object sender)
	    {
	        if(sender == addAuthorExpander)
	        {
	            selectAuthorExpander.IsExpanded = false;
	        }
	        else
	        {
	            addAuthorExpander.IsExpanded = false;
	        }
	    }

        private void addSelectedAuthor_Click(object sender, RoutedEventArgs e)
        {
            var items = authorsList.SelectedItems;
            foreach (AuthorViewModel item in items)
            {
                AddAuthor(item);
            }
        }

        /// <summary>
        /// Adds the author to the book's author list.
        /// </summary>
        /// <param name="author">The author.</param>
        void AddAuthor(AuthorViewModel author)
        {
            
            if (!_book.Authors.Contains(author))
            {
                _book.Authors.Add(author);
            }
        }

        /// <summary>
        /// Gets the authors from the book's author list.
        /// </summary>
        void GetAuthors()
        {
            authors.ItemsSource = _book.Authors;
        }

        private void LinkCreator_LinkSaved(object sender, LinkSavedEventArgs e)
        {
            _book.Links.Add(e.LinkVM);
            LoadLinks();
        }

        private void AddCover_CoverAdded(object sender, CoverAddedEventArgs e)
        {
            _book.Cover.Add(e.CoverVM);
            LoadCovers();
        }

        private void MenuItem_Click(object sender, RoutedEventArgs e)
        {
            DictionaryManager manager = null;
            if (sender == AddPublisher || sender == EditPublishers)
            {
                manager = new DictionaryManager(Dictionary.Publisher);
                if (sender == AddPublisher)
                {
                    manager.SetAddDefault();
                }
                else
                {
                    manager.SetEditDefault(Publishers.SelectedItem);
                }
            }
            else if (sender == AddBinding|| sender == EditBinding)
            {
                manager = new DictionaryManager(Dictionary.Binding);
                if (sender == AddBinding)
                {
                    manager.SetAddDefault();
                }
                else
                {
                    manager.SetEditDefault(format.SelectedItem);
                }
            }
            else if (sender == AddCondition || sender == EditCondition)
            {
                manager = new DictionaryManager(Dictionary.Condition);
                if (sender == AddCondition)
                {
                    manager.SetAddDefault();
                }
                else
                {
                    manager.SetEditDefault(format.SelectedItem);
                }
            }

            if (manager != null)
            {
                manager.Show();
            }
        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            
        }

        private void addAuthor_AddClicked(object sender, EventArgs e)
        {
            // Add author to list, close expander
            AddAuthor(addAuthor.Author);
            addAuthorExpander.IsExpanded = false;
        }
	}
}